﻿using GalaSoft.MvvmLight.Messaging;
using KINLO.Data.Reporitory;
using KINLO.DRV.Machine;
using KINLO.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace KINLO.UI.Main.Services
{
    public class CoreService
    {
        #region 字段
        public string Line;
        WeightReporitory DB = new WeightReporitory();
        /// <summary>
        /// FrontWeightReporitory 
        /// </summary>
        FrontWeightReporitory FDB = new FrontWeightReporitory();
        /// <summary>
        /// AfterWeightReporitory
        /// </summary>
        AfterWeightReporitory ADB = new AfterWeightReporitory();
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CoreService));
        //前扫描器
        public HWScannerMachine FrontScanner;
        //后扫描器
        public HWScannerMachine BackScanner;
        //注液机
        public OmronInjectionMachine InjectionMachine;
        //前电子称
        public List<ElecBalanceMachine> FrontElecBalances;
        //后电子称
        public List<ElecBalanceMachine> BackElecBalances;
        //补液电子称
        public List<ElecBalanceMachine> RepairElecBalances;
        #endregion

        System.Timers.Timer timer = new System.Timers.Timer(1000); 
        #region  方法
        public CoreService(string line)
        {
            try
            {
                Line = line;
                Init();
            }
            catch (Exception ex)
            {
                log.Error(string.Format("初始化发生错误:{0}", ex.Message));
            }
        }
        void Init()
        {
            Messenger.Default.Register<bool>(this, "StopInjectionMachineSvc", new Action<bool>((s) => {
                if (s)
                {  
                    InjectionMachine.Stop();
                }
                else
                { 
                        InjectionMachine.Start();  
                }
            }));
            timer.Elapsed += Timer_Elapsed;
            timer.Enabled = true;

            if (GlobalValues.FrontScanner != null)
            {
                FrontScanner = new HWScannerMachine(GlobalValues.FrontScanner.IP, GlobalValues.FrontScanner.Port , "1", 1000);
                log.Info(string.Format("前扫描器:{0},{1} 初始化完成", GlobalValues.FrontScanner.IP, GlobalValues.FrontScanner.Port));
            }
            if (GlobalValues.BackScanner != null)
            {
                BackScanner = new HWScannerMachine(GlobalValues.BackScanner.IP, GlobalValues.BackScanner.Port , "2", 1000);
                log.Info(string.Format("后扫描器:{0},{1} 初始化完成", GlobalValues.BackScanner.IP, GlobalValues.BackScanner.Port));
            }

            if (GlobalValues.InjectionMachine != null)
            {
                InjectionMachine = new OmronInjectionMachine(GlobalValues.InjectionMachine.IP, GlobalValues.InjectionMachine.Port , 400, "注液机");
                log.Info(string.Format("注液机:{0},{1} 初始化完成", GlobalValues.InjectionMachine.IP, GlobalValues.InjectionMachine.Port));
            }

            if (GlobalValues.FrontElecBalances != null && GlobalValues.FrontElecBalances.Count > 0)
            {
                FrontElecBalances = new List<ElecBalanceMachine>();
                foreach (var f in GlobalValues.FrontElecBalances)
                {
                    FrontElecBalances.Add(new ElecBalanceMachine(f.IP, f.Port , f.Name, 50, 20));
                    log.Info(string.Format("前称重电子称:{0},{1} 初始化完成", f.IP, f.Port));
                }
            }

            if (GlobalValues.BackElecBalances != null)
            {
                BackElecBalances = new List<ElecBalanceMachine>();
                foreach (var f in GlobalValues.BackElecBalances)
                {
                    BackElecBalances.Add(new ElecBalanceMachine(f.IP, f.Port , f.Name, 50, 20));
                    log.Info(string.Format("后称重电子称:{0},{1} 初始化完成", f.IP, f.Port));
                }
            }

            if (GlobalValues.RepairElecBalances != null)
            {
                RepairElecBalances = new List<ElecBalanceMachine>();
                foreach (var f in GlobalValues.RepairElecBalances)
                {
                    RepairElecBalances.Add(new ElecBalanceMachine(f.IP, f.Port , f.Name, 50, 20));
                    log.Info(string.Format("补液称重电子称:{0},{1} 初始化完成", f.IP, f.Port));
                }
            }

            Messenger.Default.Register<string>(this, "FStartScan", new Action<string>((s) => CmdFStartScan(s)));
            Messenger.Default.Register<string>(this, "FInjectionWeight", new Action<string>((s) => CmdFInjectionWeight(s)));
            Messenger.Default.Register<string>(this, "BStartScan", new Action<string>((s) => CmdBStartScan(s)));
            Messenger.Default.Register<string>(this, "BInjectionWeight", new Action<string>((s) => CmdBInjectionWeight(s)));
            Messenger.Default.Register<string>(this, "RepairLiquidWeight", new Action<string>((s) => CmdRepairLiquidWeight(s)));
            Messenger.Default.Register<string>(this, "BInjectionWeightClear", new Action<string>((s) => CmdBInjectionWeightClear(s)));
            Messenger.Default.Register<string>(this, "AInjectionWeightClear", new Action<string>((s) => CmdAInjectionWeightClear(s)));
            Messenger.Default.Register<string>(this, "RInjectionWeightClear", new Action<string>((s) => CmdRInjectionWeightClear(s)));
            log.Info("初始化完成 ");
        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (InjectionMachine != null)
            {
                Messenger.Default.Send(InjectionMachine.Connected, "InjectionStatus"); 
            }
        }


        /// <summary>
        /// 前扫描命令
        /// </summary>
        /// <param name="s"></param>
        void CmdFStartScan(string s)
        {
            try
            {
                FrontScanner.StartScan();
                var scanResult = FrontScanner.Receive().Trim();
                if (string.IsNullOrEmpty(scanResult))
                {
                    InjectionMachine.WriteFScanFin(false);
                    log.Info(string.Format("前扫码 {0} 扫描失败", FrontScanner.ID));
                }
                else
                {
                    // 查询数据库是否重码   
                    if (DB.GetBattryByBarCode(scanResult) != null)
                    {
                        InjectionMachine.WriteFScanFin(false);
                        var errorMsg = string.Format("电池条码 {0} 已存在", scanResult);
                        log.Error(string.Format("前扫码异常:{0}", errorMsg));
                        if (GlobalValues.UnQualifiedShowMsg == true)
                            Messenger.Default.Send(errorMsg, "NotUnqualified");
                        return;
                    }
                    else
                    {
                        var trayNum = InjectionMachine.D1220;
                        log.Info(string.Format("前扫码托架号:{0}", trayNum));
                        var guid = Guid.NewGuid();
                        var weight = new Weight()
                        {
                            ID = guid,
                            Index=1,
                            Stage = 1,
                            IsGoods=100,
                            LineNo=GlobalValues.Line,
                            TrayCode = trayNum.ToString(),
                            FScanTime = DateTime.Now,
                            BattBarCode = scanResult,
                            ProductDate=DateTime.Now
                        };
                        var operResult = DB.AddBattryInfo(weight);
                        if (operResult)
                        {
                            log.Info(string.Format("电池 {0} 插入成功", scanResult));

                        }
                        //插入 FrontWeigt BYD Mes
                        var frontWeight = new FrontWeight() { Eno=GlobalValues.Line,PLotNo=scanResult };
                        FDB.AddFrontWeight(frontWeight);
                        InjectionMachine.WriteFScanFin(true);
                        log.Info(string.Format("前扫码 {0} 扫描成功", FrontScanner.ID));
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        /// <summary>
        /// 注液前称重
        /// </summary>
        /// <param name="s"></param>
        void CmdFInjectionWeight(string s)
        {
            try
            {
              //  Thread.Sleep(5000);
                var trayNum = InjectionMachine.D1221;
                log.Info(string.Format("注液前托架号:{0}", trayNum));
                var batt = DB.GetBattryByTrayCode(trayNum.ToString());
                if (batt == null)
                {
                    log.Error(string.Format("注液前称重 找不到托架号 {0} 的电池信息", trayNum));
                    InjectionMachine.WriteFInjectionWeightFin();
                }
                else
                {
                    if (FrontElecBalances.Count > 0)
                    {
                        foreach (var feb in FrontElecBalances)
                        {
                           // feb.LoopRead();
                            feb.ServiceControl(true);
                        }
                        
                        while (true)
                        {
                            if (FrontElecBalances.Where(ss => ss.IsWeightFin == false).ToList().Count > 0)
                            {
                                Thread.Sleep(500);
                            }
                            else
                            {

                                batt.FInjectionWeight = FrontElecBalances[0].Weight;
                                FrontElecBalances[0].IsWeightFin = false;

                                batt.FWeightTime = DateTime.Now;
                                batt.Stage = 2;
                                //前称重范围
                                var minWeight = GlobalValues.WeightRef2 - GlobalValues.WeightWave2;
                                var maxWeight = GlobalValues.WeightRef2 + GlobalValues.WeightWave2; 
                                var range = string.Format("{0}~{1}", minWeight, maxWeight);
                                batt.Range = range;

                                //后称重范围
                                var weight = batt.FInjectionWeight + GlobalValues.WeightRef1;
                                var minBWeight = weight - GlobalValues.WeightWave1;
                                var maxBWeight = weight + GlobalValues.WeightWave1;
                                batt.Range2 = string.Format("{0}~{1}", minBWeight, maxBWeight);

                                var fBatt = FDB.GetFrontWeightByPLotNo(batt.BattBarCode);
                                if (fBatt != null)
                                {
                                    fBatt.PreWeight = batt.FInjectionWeight;
                                    fBatt.PreTime = DateTime.Now;
                                    fBatt.Result = "OK";
                                    fBatt.LimitsMin = minWeight;
                                    fBatt.LimitsMax = maxWeight;
                                }

                                //合格
                                batt.IsGoods = 100;
                                if (GlobalValues.EnableFrontInjectCheck == true)
                                {
                                    var devVal1= batt.FInjectionWeight - GlobalValues.WeightRef2;
                                    var devVal2 = Math.Abs(Decimal.Parse(devVal1.ToString()));
                                    if (devVal2 > GlobalValues.WeightWave2)
                                    {
                                        if (fBatt != null)
                                        {
                                            fBatt.Result = "NG";
                                        }
                                        if (devVal1 > 0)
                                        {
                                            //偏大
                                            batt.IsGoods = 1; 
                                            batt.DevValue = devVal1;// - GlobalValues.WeightWave2;
                                        }
                                        else
                                        {
                                            //偏小
                                            batt.IsGoods = 2;
                                            batt.DevValue = devVal1; // + GlobalValues.WeightWave2;
                                        }
                                    }
                                }
                                //更新 FrontWeigt BYD Mes
                                if(fBatt!=null)
                                    FDB.UpdateFrontWeight(fBatt);
                                batt.ProductDate = DateTime.Now;
                                DB.UpdateBattryInfo(batt);
                                break;
                            }
                        }
                        InjectionMachine.WriteFInjectionWeightFin();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        //后扫码结果
        string BscanResult = "";
        /// <summary>
        /// 后扫描命令
        /// </summary>
        /// <param name="s"></param>
        void CmdBStartScan(string s)
        {
            try
            { 
                BackScanner.StartScan();
                var scanResult = BackScanner.Receive();
                BscanResult = scanResult.Trim();
                if (!string.IsNullOrEmpty(BscanResult))
                {
                    var batt = DB.GetBattryByBarCode(BscanResult);
                    if (batt != null)
                    {
                        batt.BScanTime = DateTime.Now;
                        batt.ProductDate = DateTime.Now;
                        DB.UpdateBattryInfo(batt);
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }

        }
        /// <summary>
        /// 注液后称重
        /// </summary>
        /// <param name="s"></param>
        void CmdBInjectionWeight(string s)
        {
            try
            {
                Weight batt;
                if (string.IsNullOrEmpty(BscanResult))
                {
                    log.Info(string.Format("后扫码 {0} 扫描失败 将根据托架号查找电池", BackScanner.ID));
                    var trayNum = InjectionMachine.D1223;
                    batt = DB.GetBattryByTrayCode(trayNum.ToString()); 
                }
                else
                {
                    batt = DB.GetBattryByBarCode(BscanResult);
                }
                BWeightOper(batt);
                BscanResult = "";
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        void BWeightOper(Weight batt)
        {
            if (batt != null)
            {
                if (BackElecBalances.Count > 0)
                {
                    foreach (var beb in BackElecBalances)
                    {

                        //beb.LoopRead();
                         beb.ServiceControl(true);
                    }

                    while (true)
                    {
                        if (BackElecBalances.Where(ss => ss.IsWeightFin == false).ToList().Count > 0)
                        {
                            Thread.Sleep(500);
                        }
                        else
                        {
                            batt.Stage = 4;
                            batt.BInjectionWeight = BackElecBalances[0].Weight;

                            BackElecBalances[0].IsWeightFin = false;

                            batt.BWeightTime = DateTime.Now;

                            //BYD MES
                            var fBatt = FDB.GetFrontWeightByPLotNo(batt.BattBarCode);
                            AfterWeight aBatt=null;
                            if (fBatt != null)
                            {
                                aBatt = new AfterWeight()
                                {
                                    Eno = fBatt.Eno,
                                    PLotNo = fBatt.PLotNo,
                                    PreTime = fBatt.PreTime,
                                    PreWeight = fBatt.PreWeight,
                                    AftTime = DateTime.Now,
                                    AftWeight = batt.BInjectionWeight,
                                    LiquidWeight = batt.BInjectionWeight - fBatt.PreWeight,
                                    LimitsMin = GlobalValues.WeightRef1 - GlobalValues.WeightWave1,
                                    LimitsMax = GlobalValues.WeightRef1 + GlobalValues.WeightWave1
                                };
                                
                            }

                            //实际注液量
                            var diffValue = batt.BInjectionWeight - batt.FInjectionWeight;
                            batt.InjectionWeight = diffValue;

                            //实际偏差值
                            var devValue = diffValue - GlobalValues.WeightRef1;
                            //batt.DevValue = devValue;
                            var devVal1 = Decimal.Parse(devValue.ToString());
                            var devVal2 = System.Math.Abs(devVal1);     //转为绝对值
                            if (devVal2 < GlobalValues.WeightWave1)  //小于偏差值范围 则判定为合格
                            {
                                batt.IsGoods = 100; //OK 
                                batt.Finished = true;
                               // batt.TheoryRepairValue = 0;
                                //batt.ActualRepairValue = 0;
                                batt.ProductDate = DateTime.Now;
                                if (aBatt != null)
                                {
                                    aBatt.Result = "OK";
                                    //新增 BackWeigt BYD Mes
                                    ADB.AddAfterWeight(aBatt);
                                    //删除 FrontWeigt BYD Mes
                                    FDB.DeleteFrontWeight(fBatt.PLotNo);
                                }
                                DB.UpdateBattryInfo(batt);
                                var bat = DB.GetBattryByBarCode(batt.BattBarCode);
                                Messenger.Default.Send(bat, "UpdateBBattryInfoToUI");
                                InjectionMachine.WriteBInjectionWeightOK(true);
                                InjectionMachine.WriteBInjectionWeightFin();
                            }
                            else
                            { 
                                //后称重NG 大于0传超重值 否则传补液量值
                                if (devValue > 0)
                                {
                                   // batt.TheoryRepairValue = 0;
                                    batt.Finished = true;
                                    log.Info("后称重NG信号 大于");
                                    InjectionMachine.WriteAWeightOverVal(int.Parse(Math.Ceiling(Decimal.Parse(devValue.ToString())).ToString()));
                                }
                                else
                                {
                                    //补液值  
                                    batt.TheoryRepairValue = devVal2;
                                    batt.Finished = true;
                                    batt.RepairFinished = false;
                                    if (devValue <= -200)
                                    {
                                        batt.RepairFinished = true;
                                    }
                                    var repairVal= Math.Floor(decimal.Parse(batt.TheoryRepairValue.ToString()));
                                    //补液量*10
                                    InjectionMachine.WriteBWeightFluidInfusionVal(Convert.ToInt32((repairVal)*10));
                                    log.Info("后称重NG信号 小于");
                                    InjectionMachine.WriteBWeightLowVal();
                                }
                                batt.DevValue2 = devValue;
                                batt.IsGoods = 3;//NG
                                //batt.ActualRepairValue = 0;


                                if (aBatt != null)
                                {
                                    aBatt.Result = "NG";
                                    //新增 BackWeigt BYD Mes
                                    ADB.AddAfterWeight(aBatt);
                                    //删除 FrontWeigt BYD Mes
                                    FDB.DeleteFrontWeight(fBatt.PLotNo);
                                }
                                batt.Finished = true;
                                batt.ProductDate = DateTime.Now;
                                DB.UpdateBattryInfo(batt);
                                var bat = DB.GetBattryByBarCode(batt.BattBarCode);
                                Messenger.Default.Send(bat, "UpdateBBattryInfoToUI");
                                //if (batt.BInjectionWeight < GlobalValues.MinValue)
                                //    InjectionMachine.WriteBWeightLowVal();
                                // InjectionMachine.WriteBInjectionWeightOK(false);
                                InjectionMachine.WriteBInjectionWeightFin();
                            }
                            return;
                        }
                    }
                }
            }
            else
            {
                log.Error(string.Format("后称重找不到电池的相关信息，将直接NG处理"));
                InjectionMachine.WriteBInjectionWeightOK(false);
                InjectionMachine.WriteBInjectionWeightFin();
            }
        }
        /// <summary>
        /// 补液称重
        /// </summary>
        /// <param name="s"></param>
        void CmdRepairLiquidWeight(string s)
        {
            try
            {
                var trayNum = InjectionMachine.D1225;
                var batt = DB.GetBattryByTrayCodeInRepair(trayNum.ToString());
                if (batt == null)
                {
                    log.Error(string.Format("补液称重 根据托架号找不到相关的电池信息,将直接NG处理"));
                    InjectionMachine.WriteRepairWeightQualified(false);
                    InjectionMachine.WriteRepairWeightFin();
                }
                else
                {
                    if (RepairElecBalances.Count > 0)
                    {
                        foreach (var reb in RepairElecBalances)
                        {
                           // reb.LoopRead();
                             reb.ServiceControl(true);
                        }
                        while (true)
                        {
                            if (RepairElecBalances.Where(ss => ss.IsWeightFin == false).ToList().Count > 0)
                            {
                                Thread.Sleep(500);
                            }
                            else
                            {
                                batt.Stage = 5;
                                batt.BRepairInjectionWeight = RepairElecBalances[0].Weight;
                                batt.RepairInjectionWeight = batt.BRepairInjectionWeight - batt.BInjectionWeight;
                                batt.RepairInjectionWeightTime = DateTime.Now;
                                batt.RepairFinished = true;

                                RepairElecBalances[0].IsWeightFin = false;

                                //实际补液量
                                var devValue = batt.BRepairInjectionWeight - batt.BInjectionWeight;
                                batt.ActualRepairValue = devValue;

                                var aBatt = ADB.GetAfterWeightByPLotNo(batt.BattBarCode);
                                
                                //实际注液量-标准注液量的差值
                                var devVal3 = batt.BRepairInjectionWeight - batt.FInjectionWeight-GlobalValues.WeightRef1;
                                var devVal1 = Decimal.Parse(devVal3.ToString());
                                var devVal2 = System.Math.Abs(devVal1);     //转为绝对值
                                if (devVal2 < GlobalValues.WeightWave1)
                                {
                                    if (aBatt != null)
                                    {
                                        aBatt.AddLiquidWeight = devValue;
                                        aBatt.Result = "OK";
                                    }
                                    batt.DevValue2 = null;
                                    batt.IsGoods = 100;
                                    InjectionMachine.WriteRepairWeightQualified(true);
                                }
                                else
                                {
                                    if (aBatt != null)
                                    {
                                        aBatt.AddLiquidWeight = devValue;
                                        aBatt.Result = "NG";
                                    }
                                    batt.DevValue2 = devVal3;
                                    batt.IsGoods = 4;
                                    InjectionMachine.WriteRepairWeightQualified(false);
                                }
                                batt.InjectionWeight = batt.BRepairInjectionWeight - batt.FInjectionWeight;
                                batt.Finished = true;
                                batt.ProductDate = DateTime.Now;
                                DB.UpdateBattryInfo(batt);

                                var bat = DB.GetBattryByBarCode(batt.BattBarCode);
                                Messenger.Default.Send(bat, "UpdateBBattryInfoToUI");
                                ADB.UpdateAfterWeight(aBatt);                                

                                InjectionMachine.WriteRepairWeightFin();
                                return;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        /// <summary>
        /// 注液前称重清零
        /// </summary>
        /// <param name="s"></param>
        void CmdBInjectionWeightClear(string s)
        {
            try
            {
                if (BackElecBalances.Count > 0)
                {
                    foreach (var feb in FrontElecBalances)
                    { 
                        feb.ClearZero(); 
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        /// <summary>
        /// 注液后称重清零
        /// </summary>
        /// <param name="s"></param>
        void CmdAInjectionWeightClear(string s)
        {
            try
            {
                if (BackElecBalances.Count > 0)
                {
                    foreach (var beb in BackElecBalances)
                    { 
                        beb.ClearZero(); 
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        /// <summary>
        /// 补液称重清零
        /// </summary>
        /// <param name="s"></param>
        void CmdRInjectionWeightClear(string s)
        {
            try
            {
                if (BackElecBalances.Count > 0)
                {
                    foreach (var reb in RepairElecBalances)
                    { 
                        reb.ClearZero(); 
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        #endregion
    }
}
